/*****************************************************************************
  Copyright ?2002-2004 by Martin Cook. All rights are reserved. If you like
  this code then feel free to go ahead and use it. The only thing I ask is 
  that you don't remove or alter my copyright notice. Your use of this 
  software is entirely at your own risk. I make no claims about the 
  reliability or fitness of this code for any particular purpose. If you 
  make changes or additions to this code then please clearly mark your code 
  as yours. If you have questions or comments then please contact me at: 
  martin@codegator.com
  
  Have Fun! :o)
*****************************************************************************/

using System;
using System.Data;
using System.Security.Cryptography;
using System.Text;
using System.Security.Principal;

using CG.Security.Configuration;
using CG.Security.Data;
using CG.Security.Principal;

namespace CG.Security
{

	/// <summary>
	/// Provides static methods that supply helper utilities for authenticating 
	/// and authorizing users.
	/// </summary>
	public sealed class SecurityManager
	{

		// ******************************************************************
		// Attributes.
		// ******************************************************************

		#region Attributes

		/// <summary>
		/// The data object used to interface with the database.
		/// </summary>
		private static ISecurityData c_securityData;

		#endregion

		// ******************************************************************
		// Constructors.
		// ******************************************************************

		#region Constructors

		/// <summary>
		/// Class constructor.
		/// </summary>
		static SecurityManager()
		{
			c_securityData = DataManager.SecurityData;
		} // End SecurityManager()

		#endregion

		// ******************************************************************
		// Public methods.
		// ******************************************************************

		#region Public methods

		/// <summary>
		/// Used to authenticate a user by checking for the supplied credentials in the database.
		/// </summary>
		/// <param name="userName">The name of the user.</param>
		/// <param name="userPwd">The password of the user.</param>
		/// <returns>True if the credentials were authenticated, false otherwise.</returns>
		public static bool Authenticate(
			string userName,
			string userPwd
			)
		{

			// Should we create a hash for the password?
			if (userPwd.Length > 0)
				userPwd = SecurityManager.HashData(userPwd);

			// Authenticate in the database.
			return c_securityData.Authenticate(
				userName,
				userPwd
				);

		} // End Authenticate()

		// ******************************************************************

		/// <summary>
		/// Used to calculate the effective rights for a user. The list of 
		/// rights is built by looking at whatever roles are assigned to the 
		/// user, then looking at whatever rights are assigned to those roles. 
		/// Once that list is built it is modified by looking at whatever
		/// rights are specifically assigned to the user.
		/// </summary>
		/// <param name="userID">The identifier for the user.</param>
		/// <returns>A array of right names.</returns>
		public static string[] EffectiveRights(
			int userID
			)
		{

			// Get the effective rights from the database.
			DataSet ds = c_securityData.EffectiveRights(userID);

			// Find out how many rights were returned.
			int count = ds.Tables[0].Rows.Count;

			// Create an array to contain the rights.
			string[] rights = new string[count];

			// Loop and copy the names of the rights.
			for (int x = 0; x < count; x++)
				rights[x] = ds.Tables[0].Rows[x]["right_name"].ToString();

			// Return the array of rights.
			return rights;

		} // End EffectiveRights()

		// ******************************************************************

		/// <summary>
		/// Produces a string containing a cryptographic hash of the given string.
		/// </summary>
		/// <param name="data">The data to be hashed.</param>
		/// <returns>A cryptographic hash of the given string.</returns>
		public static string HashData(
			string data
			)
		{

			// Convert the string to a unicode array of bytes.
			byte[] msgBytes = Encoding.Unicode.GetBytes(data);

			// Calculate a hash on the data.
			SHA1Managed sha1 = new SHA1Managed();
			byte[] hashBytes = sha1.ComputeHash(msgBytes);

			// Use the string builder for increased speed.
			StringBuilder hashRet = new StringBuilder("");
			            
			// Loop and convert each digit in the hash.
			foreach (byte b in hashBytes)
				hashRet.AppendFormat("{0:X}", b);
            
			// Return the hash.
			return hashRet.ToString();

		} // End HashData()

		// ******************************************************************

		/// <summary>
		/// Produces an array containing a cryptographic hash of the given data.
		/// </summary>
		/// <param name="data">The data to be hashed.</param>
		/// <returns>A cryptographic hash of the given data.</returns>
		public static byte[] HashData(
			byte[] data
			)
		{

			// Calculate a hash on the data.
			SHA1Managed sha1 = new SHA1Managed();
			byte[] hashBytes = sha1.ComputeHash(data);

			// Return the hash.
			return hashBytes;

		} // End HashData()

		#endregion

	} // End clas SecurityManager

} // End namespace CG.Security
